home *** CD-ROM | disk | FTP | other *** search
- /*
- *-----------------------------------------------------------------------
- *
- * TFLINK - program to make TFPCX TSR running a Baycom modem on a
- * COM port appear as a serial (HOST mode) TNC on a second COM port.
- *
- * tflink.c - main module for the TFLINK program
- *
- * This program glues together a standard serial COM port and the
- * TFPCX Baycom driver TNC and firmware emulator program. In this
- * manner, a PC and Baycom modem can be used together to emulate a
- * WA8DED host-mode TNC for other external programs, for example,
- * TNT running on Linux.
- *
- *-----------------------------------------------------------------------
- */
-
- /* standard inclusion file */
- #define MAIN_MODULE 1
- #include "tflink.h"
- #include "ibmcom.h"
-
- /* imported routines */
- bool tfpcx_check();
- u_int tfpcx_version();
- bool tfpcx_request();
- u_char tfpcx_readch();
- void tfpcx_writech( u_char );
-
- bool getopts( int, char** );
-
-
- /* local definitions */
- #define TFLINK_VERSION ((1 << 8) | 0)
- #define TSR_MEMORY 0x600
- #define PIC_INTERRUPT_MASK_PORT 0x21
-
- /* interrupt numbers */
- #define INT1C 0x1C
- #define INT21 0x21
- #define INT21_TSR 0x31
- #define INT21_TERMINATE 0x4C
- #define INT21_FREE_MEM 0x49
-
-
- /* module-local variables */
- static u_char i8259bit;
- static void interrupt (*old_int_1c)( void );
-
-
- /*-----------------------------------------------------------------------*/
- /*
- * print out the options as they are set up so that the defaults are
- * visible and any overrides confirmed. -N switches this off. Note
- * that this routine predicts the base address ibmcom will use.
- */
- void printopts() {
- const int uart_base[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
- int i, width; /* loop counter, box width */
-
- /* set box width to 43 chars */
- width = 43;
-
- /* create a pretty box */
- printf( "%c", 0xda );
- for ( i=0; i<width-2; i++ ) printf( "%c", 0xc4 );
- printf( "%c\n", 0xbf );
- printf( "%c TFLINK version %2d.%02d - G0FRD %c\n", 0xb3,
- (u_int)(TFLINK_VERSION >> 8),
- (u_int)(TFLINK_VERSION & 0xFF), 0xb3 );
- printf( "%c TFPCX - interrupt 0x%02X %c\n",
- 0xb3, tfpcx_interrupt, 0xb3 );
- printf( "%c COM%1d - base address 0x%04X, %5d baud %c\n",
- 0xb3, sio_port, uart_base[sio_port-1], sio_baud, 0xb3 );
- printf( "%c", 0xc0 );
- for ( i=0; i<width-2; i++ ) printf( "%c", 0xc4 );
- printf( "%c\n", 0xd9 );
- }
-
-
- /*-----------------------------------------------------------------------*/
- /*
- * timer interrupt handler - polls TFPCX for outgoing characters
- */
- void interrupt int_1c( void )
- {
- union REGS inr,outr; /* registers */
- struct SREGS sr; /* registers */
-
- /* pass on to the original routine */
- (*old_int_1c)();
-
- /* see if UART interrupts are off - indicates request from
- foreground to terminate */
- if ( inportb( PIC_INTERRUPT_MASK_PORT ) & i8259bit ) {
-
- /* unhook the timer vector */
- disable();
- setvect( INT1C, old_int_1c );
- enable();
-
- /* deactivate the COM driver */
- com_deinstall();
-
- /* all done */
- inr.h.ah = INT21_FREE_MEM;
- sr.es = _psp;
- int86x( INT21, &inr, &outr, &sr );
- }
-
- /* shuffle stuff between the available buffers (do the real work!) */
- /* transfer any characters from the incoming serial buffer
- to tfpcx unless -R receive-only */
- if ( ! rflag )
- while ( ! com_rx_empty() )
- tfpcx_writech( (u_char)com_rx() );
-
- /* transfer what we can from tfpcx to the serial buffer */
- while ( com_tx_ready() && tfpcx_request() )
- com_tx( (int)tfpcx_readch() );
- }
-
-
- /*-----------------------------------------------------------------------*/
- /*
- * see if COM interrupts already in use - probably indicates either
- * this TSR already loaded, or something else is using the port. Note
- * that this duplicates some definitions from ibmcom.c
- */
- bool portbusy( int portnum )
- {
- const char i8259levels[] = { 4, 3, 4, 3 };
-
- /* see if the 8259 bit for this port is clear (enabled) */
- i8259bit = 1 << i8259levels[portnum-1];
- if ( ! (inportb( PIC_INTERRUPT_MASK_PORT ) & i8259bit))
- return( TRUE );
- else
- return( FALSE );
- }
-
-
- /*-----------------------------------------------------------------------*/
- /*
- * main program
- */
- void main( int argc, char** argv )
- {
- union REGS inr,outr; /* registers */
- struct SREGS sr; /* registers */
- int com_retcode; /* retcode from com_ routine */
-
- /* resolve the command line arguments */
- if (! getopts( argc, argv )) {
- printf( "\nTFLINK not installed\n" );
- exit( 1 );
- }
-
- /* handle unloading of already running TSR */
- if ( uflag ) {
- /* see if PIC IRQ set (bit clear) for the port */
- if ( ! portbusy( sio_port )) {
- printf( "\nCOM%d is not busy - TFLINK not running\n",
- sio_port );
- exit( 1 );
- }
- /* set the bit - disable PIC UART interrupts - the
- running TSR should spot this and drop out */
- outportb( PIC_INTERRUPT_MASK_PORT,
- inportb( PIC_INTERRUPT_MASK_PORT) | i8259bit );
-
- /* job done */
- if (! nflag)
- printf( "\nTFLINK unloaded\n" );
- exit( 0 );
- }
-
- /* not unload - confirm options to user unless -N used */
- if (! nflag)
- printopts();
-
- /* check that the port is not already in use (by us?) */
- if ( portbusy( sio_port )) {
- printf( "\nCOM%d is busy - TFLINK may already be running\n",
- sio_port );
- printf( "TFLINK not installed\n" );
- exit( 1 );
- }
-
- /* check for the presence of TFPCX at the expected interrupt */
- if (! tfpcx_check() ) {
- printf( "\nTFPCX not found at interrupt 0x%02X, exiting\n",
- tfpcx_interrupt );
- printf( "TFLINK not installed\n" );
- exit( 1 );
- }
-
- /* print TFPCX version installed */
- if (! nflag) {
- printf( "\nTFPCX version %d.%d found at 0x%02X\n",
- (u_int)(tfpcx_version() >> 8),
- (u_int)(tfpcx_version() & 0xFF),
- tfpcx_interrupt );
- }
-
- /* set up UART to requested data rate */
- if ( (com_retcode=com_install( sio_port )) != 0 ) {
- printf( "\ncom_install() error %d\n", com_retcode );
- printf( "TFLINK not installed\n" );
- exit( 1 );
- }
- com_raise_dtr();
- com_set_speed( sio_baud );
- com_set_parity( COM_NONE, 1 );
-
- /* hook int 1C timer clock interrupt */
- disable();
- old_int_1c = getvect( INT1C );
- setvect( INT1C, int_1c );
- enable();
-
- /* free environment space memory - not required */
- inr.h.ah = INT21_FREE_MEM;
- sr.es = (u_int)peek( _psp, 0x2C );
- int86x( INT21, &inr, &outr, &sr );
-
- /* install this program as a TSR */
- inr.h.ah = INT21_TSR;
- inr.h.al = 0x00;
- inr.x.dx = TSR_MEMORY;
- int86( INT21, &inr, &outr );
- }
-